package utils

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"encoding/hex"
	"io"
	"io/ioutil"
	"log"
	"os"
)

// 获取文件的MD5哈希值
func FileMd5(path string) string {
	file, err := os.Open(path)
	if err != nil {
		log.Println(">>> 读取文件内容失败:", err) // 错误里面包含了文件路径
		return ""
	}
	defer func() { _ = file.Close() }()
	hash := md5.New()
	_, err = io.Copy(hash, file)
	if err != nil {
		log.Println(">>> 计算文件", path, "的哈希值失败:", err)
		return ""
	}

	return hex.EncodeToString(hash.Sum(nil))
}

func PathExist(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func CopyFile(src, dst string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func() { _ = out.Close() }()
	_, err = io.Copy(out, in)
	if err != nil {
		return err
	}
	err = out.Sync()
	return err
}

// CopyFileWithPerm
func _(src, dst string) error {
	var perm os.FileMode
	if info, err := os.Stat(src); err != nil {
		return err
	} else {
		perm = info.Mode()
	}

	//Read all the contents of the  original file
	buf, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}

	//Copy all the contents to the desitination file
	err = ioutil.WriteFile(dst, buf, perm)
	return err
}

var key = []byte{0xc7, 0x24, 0xc2, 0xec, 0x97, 0x8d, 0x41, 0xb6, 0xbb, 0xd1, 0x6, 0x47, 0xec, 0x77, 0xd3, 0x7b}
var iv = []byte{0x2e, 0x74, 0x62, 0x2b, 0x19, 0xe4, 0x4a, 0x8e, 0x86, 0x19, 0x8, 0xcf, 0x8d, 0x63, 0xf1, 0xcf}

func CFBEncrypt(plainText string) string {
	block, err := aes.NewCipher(key)
	if err != nil {
		log.Fatalln(">>> CFB方式加密失败:", err)
	}

	plainBytes := []byte(plainText)
	cipherBytes := make([]byte, len(plainBytes))

	cfb := cipher.NewCFBEncrypter(block, iv)
	cfb.XORKeyStream(cipherBytes, plainBytes)
	cipherText := hex.EncodeToString(cipherBytes)
	return cipherText
}

func CFBDecrypt(cipherText string) string {
	block, err := aes.NewCipher(key)
	if err != nil {
		log.Fatalln(">>> CFB方式解密失败:", err)
	}

	cipherBytes, _ := hex.DecodeString(cipherText)
	plainBytes := make([]byte, len(cipherBytes))

	cfb := cipher.NewCFBDecrypter(block, iv)
	cfb.XORKeyStream(plainBytes, cipherBytes)
	plainText := string(plainBytes)
	return plainText
}

func CFBDecryptByRef(cipherText *string) {
	plainText := CFBDecrypt(*cipherText)
	if len(plainText) > 0 {
		*cipherText = plainText
	}
}
